import cpp

/** Identify facebook::yoga namespace */
predicate isFacebookYogaNamespace(Namespace ns) { ns.getQualifiedName() = "facebook::yoga" }

/** Check if file path contains yoga/yoga */
predicate isYogaSourceFile(File f) { f.getAbsolutePath().matches("%yoga/yoga%") }

/** Check if location is within yoga namespace or yoga source files */
predicate isWithinYogaContext(Location loc) {
  exists(Namespace ns |
    isFacebookYogaNamespace(ns) and
    loc.getFile() = ns.getADeclaration().getLocation().getFile()
  )
  or
  isYogaSourceFile(loc.getFile())
}

/** Identify yoga elements through various means */
predicate usesYogaElement(Expr e) {
  exists(Type t |
    t = e.getType().getUnspecifiedType() and
    (
      t.(UserType).getQualifiedName().matches("facebook::yoga%")
      or
      t.(Class).getNamespace().getQualifiedName() = "facebook::yoga"
      or
      t.(Struct).getNamespace().getQualifiedName() = "facebook::yoga"
      or
      t.(Enum).getNamespace().getQualifiedName() = "facebook::yoga"
    )
  )
  or
  exists(FunctionCall fc |
    fc = e and
    fc.getTarget().getNamespace().getQualifiedName() = "facebook::yoga"
  )
}

from Expr e
where
  usesYogaElement(e) and
  not isWithinYogaContext(e.getLocation())
select e.getLocation().getFile().getBaseName(), e.getLocation().getStartLine(), e,
  "Uses facebook::yoga functionality"
